﻿using System;
using System.Data;
using System.Data.SqlClient;
using DayPilot.Web.Ui;
using DayPilot.Web.Ui.Enums;
using AssignmentSWEN3.App_Code;

namespace AssignmentSWEN3
{
    public partial class BookingView : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // prevent invalid ViewState errors in Firefox
            if (Request.Browser.Browser == "Firefox") Response.Cache.SetNoStore();

            if (!IsPostBack)
            {
                loadResources();

                DayPilotScheduler1.StartDate = new DateTime(DateTime.Today.Year, 1, 1);
                DayPilotScheduler1.DataSource = dbGetEvents(DayPilotScheduler1.StartDate, DayPilotScheduler1.Days);
                DayPilotScheduler1.DataBind();

                // scroll to this month
                DateTime firstOfMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
                DayPilotScheduler1.SetScrollX(firstOfMonth);

            }
        }

        protected void DayPilotScheduler1_EventMove(object sender, DayPilot.Web.Ui.Events.EventMoveEventArgs e)
        {
            string id = e.Value;
            DateTime start = e.NewStart;
            DateTime end = e.NewEnd;
            string resource = e.NewResource;

            string message = null;

            if (!dbIsFree(id, start, end, resource))
            {
                message = "The reservation cannot overlap with an existing reservation.";
            }
            else if (e.OldEnd <= DateTime.Today)
            {
                message = "This reservation cannot be changed anymore.";
            }
            else if (e.OldStart < DateTime.Today)
            {
                if (e.OldResource != e.NewResource)
                {
                    message = "The room cannot be changed anymore.";
                }
                else
                {
                    message = "The reservation start cannot be changed anymore.";
                }
            }
            else if (e.NewStart < DateTime.Today)
            {
                message = "The reservation cannot be moved to the past.";
            }
            else
            {
                dbUpdateEvent(id, start, end, resource);
                //message = "Reservation moved.";
            }

            DayPilotScheduler1.DataSource = dbGetEvents(DayPilotScheduler1.StartDate, DayPilotScheduler1.Days);
            DayPilotScheduler1.DataBind();
            DayPilotScheduler1.Update(message);
        }

        private DataTable dbGetEvents(DateTime start, int days)
        {
            SqlDataAdapter da = new SqlDataAdapter("SELECT [id], [name], [eventstart], [eventend], [resource_id], [status] FROM [event] WHERE NOT (([eventend] <= @start) OR ([eventstart] >= @end))", ConnectionClass.Get(this));
            da.SelectCommand.Parameters.AddWithValue("start", start);
            da.SelectCommand.Parameters.AddWithValue("end", start.AddDays(days));
            DataTable dt = new DataTable();
            da.Fill(dt);
            return dt;
        }

        private void dbUpdateEvent(string id, DateTime start, DateTime end, string resource)
        {
            using (SqlConnection con = new SqlConnection(ConnectionClass.Get(this)))
            {
                con.Open();
                SqlCommand cmd = new SqlCommand("UPDATE [event] SET eventstart = @start, eventend = @end, resource_id = @resource WHERE id = @id", con);
                cmd.Parameters.AddWithValue("id", id);
                cmd.Parameters.AddWithValue("start", start);
                cmd.Parameters.AddWithValue("end", end);
                cmd.Parameters.AddWithValue("resource", resource);
                cmd.ExecuteNonQuery();
            }
        }

        private bool dbIsFree(string id, DateTime start, DateTime end, string resource)
        {
            // event with the specified id will be ignored

            SqlDataAdapter da = new SqlDataAdapter("SELECT count(id) as count FROM [event] WHERE NOT (([eventend] <= @start) OR ([eventstart] >= @end)) AND resource_id = @resource AND id <> @id", ConnectionClass.Get(this));
            da.SelectCommand.Parameters.AddWithValue("id", id);
            da.SelectCommand.Parameters.AddWithValue("start", start);
            da.SelectCommand.Parameters.AddWithValue("end", end);
            da.SelectCommand.Parameters.AddWithValue("resource", resource);
            DataTable dt = new DataTable();
            da.Fill(dt);

            int count = Convert.ToInt32(dt.Rows[0]["count"]);
            return count == 0;
        }

        private void loadResources()
        {
            DayPilotScheduler1.Resources.Clear();

            string roomFilter = "0";
            if (DayPilotScheduler1.ClientState["filter"] != null)
            {
                roomFilter = (string)DayPilotScheduler1.ClientState["filter"]["room"];
            }

            SqlDataAdapter da = new SqlDataAdapter("SELECT [id], [name], [bath], [beds] FROM [resource] WHERE beds = @beds or @beds = '0'", ConnectionClass.Get(this));
            da.SelectCommand.Parameters.AddWithValue("beds", roomFilter);
            DataTable dt = new DataTable();
            da.Fill(dt);

            foreach (DataRow r in dt.Rows)
            {
                string name = (string)r["name"];
                string id = (string)r["id"];
                string bath = (string)r["bath"];
                int beds = Convert.ToInt32(r["beds"]);
                string bedsFormatted = (beds == 1) ? "1 bed" : String.Format("{0} beds", beds);

                Resource res = new Resource(name, id);
                res.Columns.Add(new ResourceColumn(bedsFormatted));
                res.Columns.Add(new ResourceColumn(bath));

                DayPilotScheduler1.Resources.Add(res);
            }

        }

        protected void DayPilotScheduler1_Command(object sender, DayPilot.Web.Ui.Events.CommandEventArgs e)
        {
            switch (e.Command)
            {
                case "refresh":
                    DayPilotScheduler1.DataSource = dbGetEvents(DayPilotScheduler1.StartDate, DayPilotScheduler1.Days);
                    DayPilotScheduler1.DataBind();
                    DayPilotScheduler1.Update();
                    break;
                case "filter":
                    loadResources();
                    DayPilotScheduler1.DataSource = dbGetEvents(DayPilotScheduler1.StartDate, DayPilotScheduler1.Days);
                    DayPilotScheduler1.DataBind();
                    DayPilotScheduler1.Update(CallBackUpdateType.Full);
                    break;
            }
        }

        protected void DayPilotScheduler1_EventResize(object sender, DayPilot.Web.Ui.Events.EventResizeEventArgs e)
        {
            string id = e.Value;
            DateTime start = e.NewStart;
            DateTime end = e.NewEnd;
            string resource = e.Resource;

            string message = null;

            if (!dbIsFree(id, start, end, resource))
            {
                message = "The reservation cannot overlap with an existing reservation.";
            }
            else if (e.OldEnd <= DateTime.Today)
            {
                message = "This reservation cannot be changed anymore.";
            }
            else if (e.OldStart != e.NewStart)
            {
                if (e.OldStart < DateTime.Today)
                {
                    message = "The reservation start cannot be changed anymore.";
                }
                else if (e.NewStart < DateTime.Today)
                {
                    message = "The reservation cannot be moved to the past.";
                }
            }
            else
            {
                dbUpdateEvent(id, start, end, resource);
                //message = "Reservation updated.";
            }

            DayPilotScheduler1.DataSource = dbGetEvents(DayPilotScheduler1.StartDate, DayPilotScheduler1.Days);
            DayPilotScheduler1.DataBind();
            DayPilotScheduler1.Update(message);
        }

        protected void DayPilotScheduler1_BeforeEventRender(object sender, DayPilot.Web.Ui.Events.Scheduler.BeforeEventRenderEventArgs e)
        {
            e.InnerHTML = String.Format("{0} ({1:d} - {2:d})", e.Text, e.Start, e.End);
            int status = Convert.ToInt32(e.Tag["status"]);
            switch (status)
            {
                case 0: // new
                    if (e.Start < DateTime.Today.AddDays(2)) // must be confirmed two day in advance
                    {
                        e.DurationBarColor = "red";
                        e.ToolTip = "Expired (not confirmed in time)";
                    }
                    else
                    {
                        e.DurationBarColor = "orange";
                        e.ToolTip = "New";
                    }
                    break;
                case 1:  // confirmed
                    if (e.Start < DateTime.Today || (e.Start == DateTime.Today && DateTime.Now.TimeOfDay.Hours > 18))  // must arrive before 6 pm
                    {
                        e.DurationBarColor = "red";
                        e.ToolTip = "Late arrival";
                    }
                    else
                    {
                        e.DurationBarColor = "green";
                        e.ToolTip = "Confirmed";
                    }
                    break;
                case 2: // arrived
                    if (e.End < DateTime.Today || (e.End == DateTime.Today && DateTime.Now.TimeOfDay.Hours > 11))  // must checkout before 10 am
                    {
                        e.DurationBarColor = "red";
                        e.ToolTip = "Late checkout";
                    }
                    else
                    {
                        e.DurationBarColor = "blue";
                        e.ToolTip = "Arrived";
                    }
                    break;
                case 3: // checked out
                    e.DurationBarColor = "gray";
                    e.ToolTip = "Checked out";
                    break;
                default:
                    throw new ArgumentException("Unexpected status.");
            }
        }

        protected void DayPilotScheduler1_BeforeCellRender(object sender, DayPilot.Web.Ui.Events.BeforeCellRenderEventArgs e)
        {
            if (e.Start < DateTime.Today)
            {
                if (e.IsBusiness)
                {
                    e.BackgroundColor = "#D5D5C0";
                }
                else
                {
                    e.BackgroundColor = "#D5CFB3";
                }
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            Response.Redirect("HouseKeepingView.aspx");               
        }

        protected void Button2_Click(object sender, EventArgs e)
        {
            Response.Redirect("Reporting.aspx");
        }
    }
}
